/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_zml.htm
 *
 * Zhiqim Zml is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.zml.expression.operator;

import java.lang.reflect.Field;

import org.zhiqim.kernel.Z;
import org.zhiqim.kernel.util.Classes;
import org.zhiqim.zml.ZmlEngine;
import org.zhiqim.zml.ZmlVariable;
import org.zhiqim.zml.exception.ExpressionException;
import org.zhiqim.zml.exception.PropertNotExistException;
import org.zhiqim.zml.expression.Operator;

/**
 * 属性表达式，来自两种方式
 * 1.点号表示法：variable.property
 * 2.索引表示法：variable["property"]
 *
 * @version v1.0.0 @author zouzhigang 2016-12-23 新建与整理
 */
public class _Property extends Operator
{
    private String variable;
    private Class<?> clazz;
    private Object target;
    
    private final String property;
    
    public _Property(String variable, String property)
    {
        this.variable = variable;
        this.property = property;
    }
    
    public _Property(Class<?> clazz, String property)
    {
        this.clazz = clazz;
        this.property = property;
    }
    
    public _Property(Object target, String property)
    {
        this.target = target;
        this.property = property;
    }
    
    @Override
    public int getType()
    {
        return PROPERTY;
    }

    @Override
    public Object build(ZmlVariable variableMap) throws ExpressionException
    {
        ExpressionException.asserts(clazz != null || variable != null || target != null, "属性表达式{"+this+"}，实例和类不能都为null");
        ExpressionException.assertNotNull(property, "属性表达式{"+this+"}，属性名不能为null");
        
        if (target != null)
        {//实例属性
            Field field = Classes.getFieldDeep(target.getClass(), property);
            if (field != null)
            {//找到字段，则表示定义是正确的
                return Classes.getFieldValue(target, field);
            }
        }
        else if (clazz != null)
        {//静态属性
            Field field = Classes.getFieldStaticDeep(clazz, property);
            if (field != null)
            {//找到字段，则表示定义是正确的
                return Classes.getFieldValue(null, field);
            }
        }
        else
        {//通过名称先判断实例属性还判断静态属性
            
            //1.先查实例属性
            Object obj = variableMap.get(variable);
            if (obj != null)
            {
                Field field = Classes.getFieldDeep(obj.getClass(), property);
                if (field != null)
                {//找到字段，则表示定义是正确的
                    return Classes.getFieldValue(obj, field);
                }
            }
            
            //2 再查静态属性
            Class<?> clazz = ZmlEngine.getJavaClass(variable);
            if (clazz == null)
                clazz = Z.cls().forName(variable);
            
            if (clazz != null)
            {
                Field field = Classes.getFieldStaticDeep(clazz, property);
                if (field != null)
                {//找到字段，则表示定义是正确的
                    return Classes.getFieldValue(null, field);
                }
            }
        }
        
        throw new PropertNotExistException("未找到对应的属性");
    }
}
